#include <kutils.h>
#include <string.h>
#include "display.h"
#include "keyboard.h"
#include "syscall.h"
#include "vfs.h"
#include "memory.h"

void set_cursor_handler(syscall_regs_t *r);
void set_pointer_handler(syscall_regs_t *r);
void set_color_handler(syscall_regs_t *r);
void display_reset_handler(syscall_regs_t *r);
s32int txt_open_fs(fs_node_t *node);
s32int txt_close_fs(fs_node_t *node);
s32int txt_write_fs(fs_node_t *node, u32int offset, u32int size, u8int *buffer);
s32int txt_create_dev_file(s8int *name);

extern fs_node_t *fs_root;

void set_cursor_handler(syscall_regs_t *r)
{
	set_cursor(r->arg1, r->arg2);
	r->res1 = csr_x;
	r->res2 = csr_y;
	r->success = 1;
}

void set_pointer_handler(syscall_regs_t *r)
{
	set_pointer(r->arg1, r->arg2);
	r->res1 = ptr_x;
	r->res2 = ptr_y;
	r->success = 1;
}

void set_color_handler(syscall_regs_t *r)
{
	settextcolor((u8int)r->arg1, (u8int)r->arg2);
	r->res1 = r->arg1;
	r->res2 = r->arg2;
	r->success = 1;
}

void display_reset_handler(syscall_regs_t *r)
{
	r->res1 = 0; r->res2 = 0; r->res3 = 0;
	if(r->arg2)
	{//reset the screen color
		settextcolor(VGA_WHITE, VGA_BLACK);
		r->res2 = 1;
	}
	if(r->arg1)
	{//clear the screen
		clear_screen();
		r->res1 = 1;
	}
	if(r->arg3)
	{//reset the cursor's position
		set_cursor(0,0);
		r->res3 = 1;
	}
	r->success = 1;
}
/*
 * end
 */

s32int txt_open_fs(fs_node_t *node)
{
	if(!node)
		return 0;
	return 1;
}

s32int txt_close_fs(fs_node_t *node)
{
	if(!node)
		return 0;
	return 1;
}

s32int txt_write_fs(fs_node_t *node, u32int offset, u32int size, u8int *buffer)
{
	if(!node)
		return 0;
	
	offset = 0;//ignore the offset
	
	if(strlen((s8int*)buffer) != (s32int)size)//they must match
		return 0;

	write_string((s8int*)buffer);
	
	return 1;
}

s32int txt_create_dev_file(s8int *name)
{
	fs_node_t *dev_node = fs_root->first_child;

	if(!dev_node)
		return 0;	

	fs_node_t *new_node = (fs_node_t*)kmalloc(sizeof(fs_node_t));
	strcpy((s8int*)new_node->name,name);
	new_node->length = 0;
	new_node->inode = get_valid_inode();
	new_node->flags = FS_FILE;
	new_node->read = 0;
   new_node->write = &txt_write_fs;
   new_node->open = &txt_open_fs;
   new_node->close = &txt_close_fs;
   new_node->ptr = 0;
	new_node->dvr_num = 0;
	new_node->dvr_ptr = 0;
	new_node->parent = dev_node;//it's parent is the /dev node
	new_node->next_sibling = 0;
	new_node->first_child = 0;

	if(dev_node->first_child == 0)//the dev node has no children at this time
	{
		dev_node->first_child = new_node;
	}
	else//the dev node alredy has atleast one child, let's add this new one to the end of the linked list
	{
		fs_node_t *tmp_node = dev_node->first_child;
		while(tmp_node)
		{
			if(tmp_node->next_sibling)
			{
				tmp_node = tmp_node->next_sibling;
			}
			else
			{
				tmp_node->next_sibling = new_node;
				break;
			}
		}
	}

	return 1;
}

void init_video_interface(void)
{
	txt_create_dev_file("txt");
	install_syscall(SYS_DISPLAY_CURSOR, set_cursor_handler);
	install_syscall(SYS_DISPLAY_POINTER, set_pointer_handler);
	install_syscall(SYS_DISPLAY_COLOR, set_color_handler);
	install_syscall(SYS_DISPLAY_RESET, display_reset_handler);
}
